
import json
from setting import *
from db_function import DataBaseFunction
import paho.mqtt.client as mqtt

class TaskSentry:

    def __init__(self) -> None:

        logger.info("__________ sentry task start __________")

        logger.info("同步子任务和母任务状态")

        self.tasks_and_downlink_synchronization() # 同步子任务和母任务状态

        logger.info("同步完成的任务到数据中心")

        self.tasks_and_data_center_synchronization() # 同步完成的任务到数据中心

        logger.info("下发传感器升级任务")

        self.downlinks_sensor_update_task() # 下发传感器升级任务

        logger.info("__________ sentry task end __________")
        logger.info("")


    @staticmethod
    def mqtt_send_data_to_data_center(data):

        '''发送数据到mqtt
        data :{
            "type": "callback"
            "data":{
                "task_type": "gateways_info",
                "task_id": "1", 																	# 任务ID号
                "task_status": "receive",                                                           # receive 接收 success 成功 fail 失败
                "notes": null,																		# 回调说明，任务失败原因
                "result": null,																		# 回调结果 有回调结果传结果
            }
        }
        '''
        # 连接 MQTT 代理
        client = mqtt.Client()

        # 建立连接
        client.connect(MQTT_DATA_CENTER_HOST, MQTT_DATA_CENTER_PORT, 60)

        payload = json.dumps(data)

        logger.info(f"数据提交远程中心端口: {MQTT_DATA_CENTER_SUBSCRIPTION_TOPIC}")

        # 发布数据到指定主题
        client.publish(MQTT_DATA_CENTER_SUBSCRIPTION_TOPIC, payload)

        # 断开 MQTT 连接
        client.disconnect()

    def send_data_to_mqtt(self, data, topic): 

        '''发送数据到基站
        data :{
                    "data": command,
                    "devaddr": devaddr,
                    "port": 12
                }
        '''
        # 连接 MQTT 代理
        client = mqtt.Client()
        # client.connect("mqtt_broker_address", 1883)  # 替换为您的 MQTT 代理地址和端口

        # 建立连接
        client.connect(MQTT_LOCAL_HOST, MQTT_LOCAL_PORT, 60)


        payload = json.dumps(data)

        # 发布数据到指定主题
        client.publish(topic, payload)

        # 断开 MQTT 连接
        client.disconnect()

    def tasks_and_data_center_synchronization(self):
        '''本地tasks表中成功或失败的任务回调给中心'''

        with DataBaseFunction() as db:

            complex_task_list = db.selete_tasks_by_status_complete() # 已经完成的任务列表，包含success 和fail

            for task in complex_task_list:

                callback_data = {
                    "type": "callback",

                    "data":{
                        "task_type": task["task_type"],
                        "task_id": task["task_id"], 
                        "task_status": task["status"], 
                        "notes": None, 
                        "result": task["return_data"], 
                    }
                }

                self.mqtt_send_data_to_data_center(callback_data) # 发送callback_数据

                db.update_tasks_status(task["task_id"], task["status"]+"-push")



    def tasks_and_downlink_synchronization(self): 
        '''查找downlink_tasks任务完成情况并更改母任务表tasks的状态'''

        with DataBaseFunction() as db:

            success_task_list = db.selete_tasks_by_status("execute") # 找出正在执行的母任务

            logger.info("master task executeing task:")

            logger.info(success_task_list)

            for i in success_task_list:

                task_id = i["task_id"]

                lst = db.selete_downlink_tasks_by_tasks_table_id(i["task_id"]) # 找出子任务

                logger.info(f"task_id：{task_id}")

                logger.info(f"子任务：{lst}")

                if any(item.get('status') in ['wait', 'execute'] for item in lst): # 如果有子任务状态为wait 和 excute 跳过

                    continue
                
                logger.info(f"~~~~~~~~~~~~")

                if all(item['status'] == 'success' for item in lst): # 所有子任务状态都为 success

                    return_data = json.dumps({i["sensor_mac"]: i["return_data"] for i in lst})

                    with DataBaseFunction() as db:

                        db.update_tasks_return_data(task_id, return_data) # 插入return_data

                        db.update_tasks_status(task_id, "success") # 更改tasks表中的任务状态

                if any(item['status'] == 'fail' for item in lst): # 子任务状态有 fail 的

                    return_data = json.dumps({i["sensor_mac"]: i["return_data"] for i in lst})

                    with DataBaseFunction() as db:

                        db.update_tasks_return_data(task_id, return_data) # 插入return_data

                        db.update_tasks_status(task_id, "fail") # 更改tasks表中的任务状态


    def downlinks_sensor_update_task(self):
        """下发传感器升级任务"""

        with DataBaseFunction() as db:

            base_station_mac_list = db.select_base_station_mac_by_sensor_upgrade()

            for base_station_mac in base_station_mac_list:

                task_list = db.get_sensor_update_task_list(base_station_mac) # 获取要升级的传感器任务

                for task in task_list:

                    base_station_mac = task["base_station_mac"]

                    task_ = json.loads(task["data_json"])

                    task_["downlink_task_id"] = task["id"]

                    task_["sensor_mac"] = task["sensor_mac"]

                    self.send_data_to_mqtt(json.dumps(task_), f"{base_station_mac}_transcations")

                    db.update_downlink_tasks_status(task_id=task[id], status='execute')


if __name__ == "__main__":

    t = TaskSentry()
